package com.cloudlead.common.lang;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Created by dean on 2015/8/12.
 * <p>
 * 读取配置文件。
 * 首先读取classpath下的所有jar包里面conf文件夹下的所有属性文件；
 * 然后读取当前项目下的conf文件夹下的所有属性文件，同名的属性会覆盖；
 * 最后读取本地文件路径相对项目前一个路径下的conf文件夹下的所有属性文件，同名的属性会覆盖。
 */
public final class Configs {
    private static ResourceBundle resourceBundle;

    private static final String PRI_PROPERTIES_FILE_PATH = "../conf/";

    private static final String PROPERTIES_CLASSPATH_PATH = "conf/";

    private static final String PROPERTIES_FILE_POSTFIX = "properties";

    static {
        try {
            Messages.AggregateBundle aggregateBundle = new Messages.AggregateBundle();
            ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            //加载所有jar包下的配置文件
            Enumeration<URL> resources = contextClassLoader.getResources(PROPERTIES_CLASSPATH_PATH);
            List<URL> resourceList = new ArrayList<>();
            while (resources.hasMoreElements()) {
                URL url = resources.nextElement();
                resourceList.add(url);
            }
            addResourceBundles(aggregateBundle, resourceList);
            //加载当前jar包下的配置文件
            URL resource = contextClassLoader.getResource(PROPERTIES_CLASSPATH_PATH);
            resourceList.clear();
            resourceList.add(resource);
            addResourceBundles(aggregateBundle, resourceList);
            //加载用户路径下的配置文件
            String relativelyPath = System.getProperty("user.dir");
            File path = new File(relativelyPath, PRI_PROPERTIES_FILE_PATH);
            resource = path.toURI().toURL();
            resourceList.clear();
            resourceList.add(resource);
            addResourceBundles(aggregateBundle, resourceList);

            resourceBundle = aggregateBundle;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void addResourceBundles(Messages.AggregateBundle resourceBundles, List<URL> resources) {
        for (URL url : resources) {
            URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
            if ("jar".equals(url.getProtocol())) {
                JarFile jarFile = null;
                try {
                    URLConnection conn = url.openConnection();
                    JarURLConnection jarCon = (JarURLConnection) conn;
                    jarFile = jarCon.getJarFile();
                    for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {
                        JarEntry entry = entries.nextElement();
                        String entryPath = entry.getName();
                        int lastIndexOf = entryPath.lastIndexOf(".");
                        if (lastIndexOf > 0) {
                            String shortName = entryPath.substring(0, lastIndexOf);
                            String postfix = entryPath.substring(lastIndexOf + 1);
                            if (entryPath.startsWith(PROPERTIES_CLASSPATH_PATH) && PROPERTIES_FILE_POSTFIX.equals(postfix)) {
                                ResourceBundle resourceBundle = ResourceBundle.getBundle(shortName, Locale.ROOT, classLoader);
                                resourceBundles.addBundle(resourceBundle);
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (null != jarFile) {
                        try {
                            jarFile.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            } else {
                File path = new File(url.getPath());
                if (path.exists() && path.isDirectory()) {
                    File[] files = path.listFiles();
                    for (File file : files) {
                        String fileName = file.getName();
                        int lastIndexOf = fileName.lastIndexOf(".");
                        if (lastIndexOf > 0) {
                            String shortName = fileName.substring(0, lastIndexOf);
                            String postfix = fileName.substring(lastIndexOf + 1);
                            if (PROPERTIES_FILE_POSTFIX.equals(postfix)) {
                                ResourceBundle resourceBundle = ResourceBundle.getBundle(shortName, Locale.ROOT, classLoader);
                                resourceBundles.addBundle(resourceBundle);
                            }
                        }
                    }
                }
            }
        }
    }

    public static String getString(String key) {
        return resourceBundle.getString(key);
    }

    public static String getString(String key, String defaultValue) {
        String value = resourceBundle.getString(key);
        if (null == value) {
            value = defaultValue;
        }
        return value;
    }

    public static Object getObject(String key) {
        return resourceBundle.getObject(key);
    }

    public static String[] getStringArray(String key) {
        return resourceBundle.getStringArray(key);
    }

}
